'use strict';
const path = require('path');
const rootDir = path.join(__dirname);
const srcDir = 'src';
const destDir = 'dest';
const gulp = require('gulp');
const gulpPostcss = require('gulp-postcss');
const autoprefixer = require('autoprefixer');
const stylelint = require('stylelint');
const gulpBabel = require('gulp-babel');
const gulpConcat = require('gulp-concat');
const gulpEslint = require('gulp-eslint');
const gulpHtmlhint = require('gulp-htmlhint');
const gulpHtmlmin = require('gulp-htmlmin');
const gulpIf = require('gulp-if');
const gulpTap = require('gulp-tap');
const gulpInclude = require('gulp-include');
const gulpFileInclude = require('gulp-file-include');
const gulpSourcemaps = require('gulp-sourcemaps');
const gulpRename = require('gulp-rename');
const gulpUglifyEs = require('gulp-uglify-es').default;
const gulpSass = require('gulp-sass');
gulpSass.compiler = require('node-sass');
const del = require('del');
const env = process.env.RELEASE_TYPE || 'dev';
// 处理工具配置
const config = require('./gulpfile.config.js')[env];
// 项目数组
const projects = require(`${rootDir}/.yi-gulp.js`);
// 任务集合
const tasks = {};
// 构建数组
const buildArray = [];

// 添加postCss插件
// postcssArray.push(stylelint());
config.postcssParams.push(autoprefixer({}));

// 清除任务
function taskClean(item) {
    return function clean() {
        return del(`${destDir}/${item.name}`);
    };
}

// vue模板文件任务
function taskVueTemplate(item) {
    return function vueTemplate() {
        return gulp
            .src(`${srcDir}/${item.name}/{store,layout,pages,components}/**/template.vue`)
            .pipe(
                gulpTap(file => {
                    let idName = file.path
                        .replace(path.join(rootDir, srcDir, item.name), '')
                        .replace('template.vue', '')
                        .replace(/[\/\\_\-]+/g, ' ')
                        .trim()
                        .split(' ');
                    let newContents = file.contents
                        .toString()
                        .replace(/<\/template>$/gim, '</script>')
                        .replace(/^<template>/gim, `<script id="${idName.join('-')}" type="text/x-template">`)
                        .replace(/x_x/gim, idName.join('_'))
                        .replace(/xxx/gim, idName.join('-'));
                    file.contents = Buffer.from(newContents);
                })
            )
            .pipe(gulpConcat('templates.bundle.html'))
            .pipe(gulp.dest(`${srcDir}/${item.name}/.cache`));
    };
}
// css任务
function taskVueCss(item) {
    return function vueCss() {
        return gulp
            .src(`${srcDir}/${item.name}/{store,layout,pages,components}/**/*.scss`, config.srcParams)
            .pipe(
                gulpTap(file => {
                    let idName = file.path
                        .replace(path.join(rootDir, srcDir, item.name), '')
                        .replace('style.scss', '')
                        .replace(/[\/\\_\-]+/g, ' ')
                        .trim()
                        .split(' ');
                    let newContents = file.contents
                        .toString()
                        .replace(/x_x/gim, idName.join('_'))
                        .replace(/xxx/gim, idName.join('-'));
                    file.contents = Buffer.from(newContents);
                })
            )
            .pipe(gulpConcat('styles.bundle.scss'))
            .pipe(gulp.dest(`${srcDir}/${item.name}/.cache`));
    };
}

// vue模板文件任务
function taskVueJs(item) {
    return function vueJs() {
        return gulp
            .src(`${srcDir}/${item.name}/{store,layout,pages,components}/**/script.js`)
            .pipe(
                gulpTap(file => {
                    let idName = file.path
                        .replace(path.join(rootDir, srcDir, item.name), '')
                        .replace('script.js', '')
                        .replace(/[\/\\_\-]+/g, ' ')
                        .trim()
                        .split(' ');
                    let newContents = file.contents
                        .toString()
                        .replace(/x_x/gim, idName.join('_'))
                        .replace(/xxx/gim, idName.join('-'));
                    file.contents = Buffer.from(newContents);
                })
            )
            .pipe(gulpConcat('scripts.bundle.js'))
            .pipe(gulp.dest(`${srcDir}/${item.name}/.cache`));
    };
}

// vue模板文件任务
function taskVueRoute(item) {
    return function vueRoute() {
        return gulp
            .src(`${srcDir}/${item.name}/{store,layout,pages,components}/**/route.js`)
            .pipe(
                gulpTap(file => {
                    let idName = file.path
                        .replace(path.join(rootDir, srcDir, item.name), '')
                        .replace('route.js', '')
                        .replace(/[\/\\_\-]+/g, ' ')
                        .trim()
                        .split(' ');
                    let newContents = file.contents
                        .toString()
                        .replace(/x_x/gim, idName.join('_'))
                        .replace(/xxx/gim, idName.join('-'));
                    file.contents = Buffer.from(newContents);
                })
            )
            .pipe(gulpConcat('routes.bundle.js'))
            .pipe(gulp.dest(`${srcDir}/${item.name}/.cache`));
    };
}

// 项目根目录下的html任务
function taskHtml(item) {
    return function html() {
        return gulp
            .src(`${srcDir}/${item.name}/*.html`, config.srcParams)
            .pipe(
                gulpInclude({
                    ...config.includeParams,
                    includePaths: [path.join(rootDir, 'src', item.name)]
                })
            )
            .pipe(gulpIf(env === 'build', gulpHtmlmin()))
            .pipe(gulp.dest(`${destDir}/${item.name}`));
    };
}

// css任务
function taskCss(item) {
    return function css() {
        return gulp
            .src(`${srcDir}/${item.name}/css/init_*.scss`, config.srcParams)
            .pipe(gulpIf(env == 'dev', gulpSourcemaps.init({ largeFile: true })))
            .pipe(gulpSass(config.sassParams))
            .pipe(gulpPostcss(config.postcssParams))
            .pipe(gulpRename('index.css'))
            .pipe(gulpIf(env === 'dev', gulpSourcemaps.write('./maps')))
            .pipe(gulp.dest(`${destDir}/${item.name}`));
    };
}
// 项目根目录下的js任务
function taskJs(item) {
    return function js() {
        return gulp
            .src(`${srcDir}/${item.name}/init_*.js`, config.srcParams)
            .pipe(
                gulpInclude({
                    ...config.includeParams,
                    includePaths: [path.join(rootDir, 'src', item.name)]
                })
            )
            .pipe(gulpIf(env === 'dev', gulpSourcemaps.init({ largeFile: true })))
            .pipe(gulpIf(env === 'dev', gulpEslint()))
            .pipe(gulpBabel(config.babelParams))
            .pipe(gulpRename('index.js'))
            .pipe(gulpIf(env === 'dev', gulpSourcemaps.write('./maps')))
            .pipe(gulpIf(env === 'build', gulpUglifyEs(config.uflifyParams)))
            .pipe(gulp.dest(`${destDir}/${item.name}`));
    };
}

// html任务
function taskStatics(item) {
    return function statics() {
        return gulp.src(`${srcDir}/${item.name}/static/**/*`, config.srcParams).pipe(gulp.dest(`${destDir}/${item.name}/static`));
    };
}

// 单个项目构建任务
function taskBuild(item) {
    return function build() {
        let task = tasks[item.name];
        return gulp.series(task.clean, gulp.parallel(task.vueTemplate, task.vueCss, task.vueJs, task.vueRoute), gulp.parallel(task.html, task.css, task.js, task.statics));
    };
}

// 遍历项目，生成每个项目的任务
projects.forEach(item => {
    tasks[item.name] = {
        clean: taskClean(item),
        vueTemplate: taskVueTemplate(item),
        vueCss: taskVueCss(item),
        vueJs: taskVueJs(item),
        vueRoute: taskVueRoute(item),
        html: taskHtml(item),
        css: taskCss(item),
        js: taskJs(item),
        statics: taskStatics(item),
        build: taskBuild(item)
    };
    // 聚焦单项目任务
    let task = tasks[item.name];
    // 赋值构建数组
    buildArray.push(task.build());
    // 导出每个项目的构建
    exports[`build_${item.name}`] = task.build();
    // 监听构建
    gulp.watch(`${srcDir}/${item.name}/**/*.html`, task.html);
    gulp.watch(`${srcDir}/${item.name}/**/*.js`, gulp.series(task.vueJs, task.js));
    gulp.watch(`${srcDir}/${item.name}/**/*.vue`, gulp.series(task.vueTemplate, task.html));
    gulp.watch(`${srcDir}/${item.name}/**/*.scss`, gulp.series(task.vueCss, task.css));
    gulp.watch(`${srcDir}/${item.name}/static`, task.statics);
});

// =========================================================================================
// 清除公共资源
function publicClean() {
    return del(`${destDir}/public`);
}
// 复制公共静态资源
function publicStatic() {
    return gulp.src(`${srcDir}/public/static/**/*`, config.srcParams).pipe(gulp.dest(`${destDir}/public/static`));
}

// 公共css处理任务 2
function publicCss() {
    return gulp
        .src(`${srcDir}/public/css/init_*.scss`, config.srcParams)
        .pipe(gulpIf(env === 'dev', gulpSourcemaps.init({ largeFile: true })))
        .pipe(gulpSass(config.sassParams))
        .pipe(gulpPostcss(config.postcssParams))
        .pipe(gulpRename('public.css'))
        .pipe(gulpIf(env === 'dev', gulpSourcemaps.write('./maps')))
        .pipe(gulp.dest(`${destDir}/public`));
}

// 公共js处理任务
function publicJs() {
    return gulp
        .src(`${srcDir}/public/js/init_*.js`, config.srcParams)
        .pipe(gulpIf(env === 'dev', gulpSourcemaps.init({ largeFile: true })))
        .pipe(
            gulpInclude({
                hardFail: true,
                separateInputs: true,
                includePaths: [path.join(rootDir, 'src', 'public')]
            })
        )
        .pipe(gulpBabel(config.babelParams))
        .pipe(gulpIf(env === 'dev', gulpSourcemaps.write('./maps')))
        .pipe(gulpRename('public.js'))
        .pipe(gulpIf(env === 'build', gulpUglifyEs(config.uflifyParams)))
        .pipe(gulp.dest(`${destDir}/public`));
}

// 公共构建任务
function puildPublic() {
    return gulp.series(publicClean, gulp.parallel(publicStatic, publicCss, publicJs));
}

// 监听公共构建
gulp.watch(`${srcDir}/public/css/**/*.scss`, publicCss);
gulp.watch(`${srcDir}/public/js/**/*.js`, publicJs);
gulp.watch(`${srcDir}/public/static`, publicStatic);

buildArray.push(puildPublic());
// 导出所有项目任务
exports.default = gulp.series(gulp.parallel(...buildArray));
